package hamsterpolice.todo.model;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import hamsterpolice.todo.data.Criteria;
import hamsterpolice.todo.data.DataAdapter;
import hamsterpolice.todo.data.ToDoListOpenHelper;
import hamsterpolice.todo.data.UnhandledCriteriaException;
import hamsterpolice.todo.data.UserTable;

class UserDataAdapter implements DataAdapter<User> {

	private static final String TAG = "UserDataAdapter";
	private SQLiteDatabase database = null;
	private String[] allColumns = new String[] { UserTable.COLUMN_ID,
			UserTable.COLUMN_USERNAME, UserTable.COLUMN_FIRSTNAME,
			UserTable.COLUMN_LASTNAME, UserTable.COLUMN_EMAIL };

	public UserDataAdapter(Context context) {
		database = ToDoListOpenHelper.getInstance(context)
				.getWritableDatabase();
	}

	@Override
	public Cursor get(Criteria<?> criteria) throws UnhandledCriteriaException {
		if (criteria instanceof IDCriterion) {
			long id = ((IDCriterion) criteria).getValue().longValue();
			return getByID(id);
		}
		else if(criteria instanceof AuthenticationCriteria){
			AuthenticationCriteria authCriteria = (AuthenticationCriteria)criteria;
			return authenticate(authCriteria.getUsername(), authCriteria.getPasswordHash());
		}

		throw new UnhandledCriteriaException();
	}

	private Cursor getByID(long id) {
		Log.v(TAG, String.format("Getting User for id=%s", id));

		Cursor cursor = null;

		cursor = database.query(UserTable.TABLE_NAME, allColumns,
				UserTable.COLUMN_ID + " = " + id, null, null, null, null);

		return cursor;
	}
	
	private Cursor authenticate(String username, String passwordHash){
		Log.v(TAG, String.format("Authenticating User %s", username));

		Cursor cursor = null;

		cursor = database.query(UserTable.TABLE_NAME, allColumns,
				UserTable.COLUMN_USERNAME + " = ? AND " + UserTable.COLUMN_PASSWORD + " = ?", 
				new String[]{username, passwordHash}, null, null, null);
		
		return cursor;
	}

	@Override
	public long load(Cursor c, User model) {
		if (c == null || c.isClosed())
			throw new IllegalArgumentException("Cursor is null or closed.");
		if (c.isBeforeFirst() || c.isAfterLast())
			throw new RuntimeException(
					"There is no record at the cursor's current location");
		
		model.setUsername(c.getString(c.getColumnIndex(UserTable.COLUMN_USERNAME)));
		model.setFirstName(c.getString(c.getColumnIndex(UserTable.COLUMN_FIRSTNAME)));
		model.setLastName(c.getString(c.getColumnIndex(UserTable.COLUMN_LASTNAME)));
		model.setEmail(c.getString(c.getColumnIndex(UserTable.COLUMN_EMAIL)));
		
		return c.getLong(c.getColumnIndex(UserTable.COLUMN_ID));
	}

	@Override
	public long insert(User model) {
		if (!model.isNew())
			throw new IllegalArgumentException(
					"Cannot insert a model that is not new");
		Log.v(TAG, String.format("Inserting User %s", model.getUsername()));
		ContentValues content = getContentValues(model);
		return database.insertOrThrow(UserTable.TABLE_NAME, null, content);
	}

	@Override
	public boolean update(User model) {
		if (model.isNew())
			throw new IllegalArgumentException(
					"Cannot update a model that is new");
		
		if (model.isDirty()) {
			Log.v(TAG, String.format("Updating User for id=%s", model.getID()));
			ContentValues content = getContentValues(model);
			return 1 == database.update(UserTable.TABLE_NAME, content,
					UserTable.COLUMN_ID + " = " + model.getID(), null);
		}
		
		return false;
	}
	
	private ContentValues getContentValues(User model){
		ContentValues content = new ContentValues();
		content.put(UserTable.COLUMN_USERNAME, model.getUsername());
		if(model.getPasswordHash()!=null)
			content.put(UserTable.COLUMN_PASSWORD, model.getPasswordHash());
		content.put(UserTable.COLUMN_FIRSTNAME, model.getFirstName());
		content.put(UserTable.COLUMN_LASTNAME, model.getLastName());
		content.put(UserTable.COLUMN_EMAIL, model.getEmail());
		return content;
	}

	@Override
	public boolean delete(long id) {
		Log.v(TAG, String.format("Deleting User for id=%s", id));

		return 1 == database.delete(UserTable.TABLE_NAME, UserTable.COLUMN_ID + " = " + id, null);
	}
	
	

}
